package com.haoyu.number.Demo.SingleLinkedList;

/**
 * @author 蒿雨
 * @create 2021-10-28 10:46
 * 单链表的增删改查(掌握一般)
 */
public class SingleLinkedListDemo {
    public static void main(String[] args) {
        //测试一耙
        Node node = new Node(1, "小白");
        Node node1 = new Node(2, "小黄");
        Node node2 = new Node(3, "小花");
        SingleLinkedList sll = new SingleLinkedList();
        //添加
//        sll.add(node);
//        sll.add(node1);
//        sll.add(node2);
//       //排序添加
        sll.addOrder(node2);
        sll.addOrder(node);
        sll.addOrder(node1);
        sll.show();
        //修改
        Node node4 = new Node(1, "小可");
        sll.update(node4);
        System.out.println("修改后输出");
        sll.show();
        //删除
        sll.delete(1);
        System.out.println("删除后输出");
        sll.show();
    }
}


///创建一个实体类
class Node {
    public int id;
    public String name;
    public Node nextNode;

    public Node(int id, String name) {
        this.id = id;
        this.name = name;
    }

    @Override
    public String toString() {
        return "Node{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", nextNode=" + nextNode +
                '}';
    }
}

//创建链表工具类
class SingleLinkedList {
    //先初始化一个头节点，头节点不要动,不存放具体数据
    private Node headNode = new Node(0, "");

    //获取头节点
    public Node getHeadNode() {
        return headNode;
    }

    //添加节点到单向链表
    //思路：当不考虑编号的顺序是
    //1.找到当前链表的最后节点
    //2.将最后这个节点的NEXT指向新的节点
    //添加方法
    public void add(Node node) {
        //因为head节点不能动,因此我们需要一个辅助变量temp
        Node temp = node;
        //遍历链表，找到最后（当指向下一个节点为空的时候，代表下一个位置可以添加）
        while (true) {
            //找到链表的最后
            if (temp.nextNode == null) {
                break;
            }
            //如果没找到
            temp = temp.nextNode;
        }
        //当退出while循环时，temp就指向了链表的最后
        //将最后这个节点的next指向新的节点
        temp.nextNode = node;
    }

    //第二种添加方式在添加英雄时，根据排名将英雄插入到指定位置
    //(如果有这个排名，则添加失败，并给出提示)
    public void addOrder(Node node) {
        //因为头节点不能动，因此我们仍然通过一个辅助指针（变量）来找到添加的位置
        //因为单链表，因此，我们找的temp,是位于添加位置的前一个节点，否则插入不了
        Node temp = headNode;
        boolean flag = false;//标识添加的编号是否存在，默认为false
        while (true) {
            if (temp.nextNode == null) {
                //说明temp已经在链表的最后
                break;
            }
            if (temp.nextNode.id > node.id) {
                //位置找到了，就在temp后面插入
                break;
            } else if (temp.nextNode.id == node.id) {
                //说明希望添加的标号已经存在
                flag = true;
            }
            //后移，相当于在遍历当前的链表
            temp = temp.nextNode;
        }
        if (flag) {
            System.out.println("待添加数据已存在");
            return;
        } else {
            node.nextNode = temp.nextNode;
            temp.nextNode = node;
        }
    }

    //修改节点的信息,根据编号来修改，即编号不能修改
    //1.根据newHeroNode的no来修改即可
    public void update(Node node) {
        //判断受否空
        if (headNode.nextNode == null) {
            System.out.println("链表为空~");
            return;
        }
        //找到需要修改的节点
        //定义一个辅助变量
        //因为头节点不能赋值
        Node temp = headNode.nextNode;
        boolean flag = false;
        //表示是否找到该节点
        while (true) {
            //到链表的最后，遍历完了
            if (temp == null) {
                break;
            }
            //找到了
            if (temp.id == node.id) {
                flag = true;
                break;
            }
            temp = temp.nextNode;
        }
        //根据flag判断是否找到要修改的节点
        if (flag) {
            temp.id = node.id;
            temp.name = node.name;
        } else {
            System.out.printf("没有找到编号%d的节点，不能修改", node.id);
        }
    }

    //删除节点
    //思路1.head不能动，因此需要一个辅助节点，找到待删除节点的前一个节点
    //在比较时，是temp.next.no和需要删除的节点的no比较
    public void delete(int id) {
        Node temp = headNode;
        boolean flag = false;
        while (true) {
            if (temp.nextNode == null) {

                break;
            }
            if (temp.nextNode.id == id) {
                flag = true;
                break;
            }
            temp = temp.nextNode;
        }
        if (flag) {
            temp.nextNode = temp.nextNode.nextNode;
        } else {
            System.out.println("没找到");
        }
    }
    //展示方法
    public void show() {
        //判断是否为空
        if (headNode.nextNode == null) {
            System.out.println("链表为空！");
            return;
        }
        Node temp = headNode.nextNode;
        //输出链表（不输出头,取下一位节点）
        while (true) {
            if (temp == null) {
                break;
            }
            System.out.println(temp.toString());
            temp = temp.nextNode;
        }
    }
}